﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Drawing.Printing;
using System.IO;
using System.Windows.Forms;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using YArchitech.Controls;
using YArchitech.Revit;
using UnitManager;

namespace YJKBatchPrinter
{
	public class PrintMgr
	{
		public PrintMgr(ExternalCommandData commandData)
		{
			this.m_commandData = commandData;
			this.m_printMgr = commandData.Application.ActiveUIDocument.Document.PrintManager;
		}

		public List<string> InstalledPrinterNames
		{
			get
			{
				List<string> result;
				try
				{
					PrinterSettings.StringCollection installedPrinters = PrinterSettings.InstalledPrinters;
					string[] array = new string[installedPrinters.Count];
					installedPrinters.CopyTo(array, 0);
					List<string> list = new List<string>();
					foreach (string item in array)
					{
						list.Add(item);
					}
					result = ((list.Count == 0) ? null : list);
				}
				catch (Exception)
				{
					result = null;
				}
				return result;
			}
		}

		public PrintManager getRvtDocPrinter()
		{
			return this.m_printMgr;
		}

		public string PrinterName
		{
			get
			{
				return this.m_printMgr.PrinterName;
			}
			set
			{
				try
				{
					this.m_printMgr.SelectNewPrintDriver(value);
				}
				catch (Exception)
				{
				}
			}
		}

		public string PrintSetupName
		{
			get
			{
				IPrintSetting currentPrintSetting = this.m_printMgr.PrintSetup.CurrentPrintSetting;
				if (!(currentPrintSetting is PrintSetting))
				{
					return "<在任务中>";
				}
				return (currentPrintSetting as PrintSetting).Name;
			}
		}

		public bool IsPrintToFile
		{
			get
			{
				return this.m_printMgr.PrintToFile;
			}
			set
			{
				this.m_printMgr.PrintToFile = value;
				this.m_printMgr.Apply();
			}
		}

		public bool IsCombinedFile
		{
			get
			{
				return this.m_printMgr.CombinedFile;
			}
			set
			{
				this.m_printMgr.CombinedFile = value;
				this.m_printMgr.Apply();
			}
		}

		public string PrintToFileName
		{
			get
			{
				return this.m_commandData.Application.ActiveUIDocument.Document.PrintManager.PrintToFileName;
			}
		}

		public string ChangePrintToFileName()
		{
			string text;
			using (SaveFileDialog saveFileDialog = new SaveFileDialog())
			{
				string str = null;
                switch ((int)this.m_printMgr.IsVirtual)
				{
				case 0:
					saveFileDialog.Filter = "plt files (*.plt)|*.plt|prn files (*.prn)|*.prn";
					str = ".plt";
					break;
				case 1:
					saveFileDialog.Filter = "pdf files (*.pdf)|*.pdf";
					str = ".pdf";
					break;
				case 2:
					saveFileDialog.Filter = "dwf files (*.dwf)|*.dwf";
					str = ".dwf";
					break;
				case 3:
					saveFileDialog.Filter = "XPS files (*.xps)|*.xps";
					str = ".xps";
					break;
				}
				string title = this.m_commandData.Application.ActiveUIDocument.Document.Title;
				if (title.Contains(".rvt"))
				{
					saveFileDialog.FileName = title.Remove(title.LastIndexOf(".")) + str;
				}
				else
				{
					saveFileDialog.FileName = title + str;
				}
				if (saveFileDialog.ShowDialog() == DialogResult.OK)
				{
					text = (this.m_printMgr.PrintToFileName = saveFileDialog.FileName);
					text = text;
				}
				else
				{
					text = null;
				}
			}
			return text;
		}

        public Autodesk.Revit.DB.PrintRange PrintRange
		{
			get
			{
				return this.m_printMgr.PrintRange;
			}
			set
			{
				this.m_printMgr.PrintRange = value;
				this.m_printMgr.Apply();
			}
		}

		public bool Collate
		{
			get
			{
				return this.m_printMgr.Collate;
			}
			set
			{
				this.m_printMgr.Collate = value;
				this.m_printMgr.Apply();
			}
		}

		public int CopyNumber
		{
			get
			{
				return this.m_printMgr.CopyNumber;
			}
			set
			{
				this.m_printMgr.CopyNumber = value;
				this.m_printMgr.Apply();
			}
		}

		public bool PrintOrderReverse
		{
			get
			{
				return this.m_printMgr.PrintOrderReverse;
			}
			set
			{
				this.m_printMgr.PrintOrderReverse = value;
				this.m_printMgr.Apply();
			}
		}

		public string SelectedViewSheetSetName
		{
			get
			{
				IViewSheetSet currentViewSheetSet = this.m_printMgr.ViewSheetSetting.CurrentViewSheetSet;
				if (!(currentViewSheetSet is ViewSheetSet))
				{
					return "<在任务中>";
				}
				return (currentViewSheetSet as ViewSheetSet).Name;
			}
		}

		public string DocumentTitle
		{
			get
			{
				string title = this.m_commandData.Application.ActiveUIDocument.Document.Title;
				if (title.Contains(".rvt"))
				{
					return title.Remove(title.LastIndexOf(".")) + this.PostFix;
				}
				return title + this.PostFix;
			}
		}

		public string PostFix
		{
			get
			{
				string result = null;
                switch ((int)this.m_printMgr.IsVirtual)
				{
				case 0:
					result = ".prn";
					break;
				case 1:
					result = ".pdf";
					break;
				case 2:
					result = ".dwf";
					break;
				case 3:
					result = ".xps";
					break;
				}
				return result;
			}
		}

		public void ChangePrintSetup()
		{
			using (PrintSetupForm printSetupForm = new PrintSetupForm(new PrintSTP(this.m_printMgr, this.m_commandData)))
			{
				printSetupForm.ShowDialog();
			}
		}

		public void SelectViewSheetSet()
		{
			using (ViewSheetSetMgrForm viewSheetSetMgrForm = new ViewSheetSetMgrForm(this.m_commandData))
			{
				viewSheetSetMgrForm.ShowDialog();
			}
		}

		public bool SubmitPrint()
		{
			if (File.Exists(this.m_printMgr.PrintToFileName))
			{
				File.Delete(this.m_printMgr.PrintToFileName);
			}
			return this.m_printMgr.SubmitPrint();
		}

		public bool VerifyPrintToFile(System.Windows.Forms.Control controlToEnableOrNot)
		{
			return controlToEnableOrNot.Enabled = ((this.m_printMgr.IsVirtual == null) ? true : false);
		}

		public bool VerifyCopies(Collection<System.Windows.Forms.Control> controlsToEnableOrNot)
		{
			bool flag = this.m_printMgr.IsVirtual == null && !this.m_printMgr.PrintToFile;
			try
			{
				int copyNumber = this.m_printMgr.CopyNumber;
			}
			catch (Exception)
			{
				flag = false;
			}
			foreach (System.Windows.Forms.Control control in controlsToEnableOrNot)
			{
				control.Enabled = flag;
			}
			return flag;
		}

		public bool VerifyPrintToFileName(Collection<System.Windows.Forms.Control> controlsToEnableOrNot)
		{
			bool flag = this.m_printMgr.IsVirtual != null || (this.m_printMgr.IsVirtual == null && this.m_printMgr.PrintToFile);
			foreach (System.Windows.Forms.Control control in controlsToEnableOrNot)
			{
				control.Enabled = flag;
			}
			return flag;
		}

		public bool VerifyPrintToSingleFile(System.Windows.Forms.Control controlToEnableOrNot)
		{
			return controlToEnableOrNot.Enabled = (this.m_printMgr.IsVirtual > 0);
		}

		public bool VerifyPrintToSeparateFile(System.Windows.Forms.Control controlToEnableOrNot)
		{
            return controlToEnableOrNot.Enabled = ((this.m_printMgr.IsVirtual != null && (int)this.m_printMgr.PrintRange == 2) || (this.m_printMgr.IsVirtual == null && (int)this.m_printMgr.PrintRange == 2 && this.m_printMgr.PrintToFile));
		}

		public bool VerifyCollate(System.Windows.Forms.Control controlToEnableOrNot)
		{
			int num = 0;
			try
			{
				num = this.m_printMgr.CopyNumber;
			}
			catch (Autodesk.Revit.Exceptions.InvalidOperationException)
			{
			}
            return controlToEnableOrNot.Enabled = ((int)this.m_printMgr.PrintRange == 2 && !this.m_printMgr.PrintToFile && num > 1);
		}

		public bool VerifySelectViewSheetSet(Collection<System.Windows.Forms.Control> controlsToEnableOrNot)
		{
            bool flag = (int)this.m_printMgr.PrintRange == 2;
			foreach (System.Windows.Forms.Control control in controlsToEnableOrNot)
			{
				control.Enabled = flag;
			}
			return flag;
		}

		public static void MyMessageBox(string text)
		{
			YJKMessageBox.Show(text);
		}

        private Autodesk.Revit.DB.PaperSize getPaperSizeByName(string sSizeName, Autodesk.Revit.DB.PaperSizeSet sizeSet)
		{
            Autodesk.Revit.DB.PaperSize result = null;
			if (this.m_printMgr != null)
			{
				foreach (object obj in this.m_printMgr.PaperSizes)
				{
                    Autodesk.Revit.DB.PaperSize paperSize = obj as Autodesk.Revit.DB.PaperSize;
					if (paperSize != null && paperSize.Name.Equals(sSizeName))
					{
						result = paperSize;
						break;
					}
				}
			}
			return result;
		}

		private Dictionary<string, List<Autodesk.Revit.DB.View>> createSizeGroup(ViewSet views, Autodesk.Revit.DB.Document doc, string sCurSizeName)
		{
			Dictionary<string, List<Autodesk.Revit.DB.View>> dictionary = new Dictionary<string, List<Autodesk.Revit.DB.View>>();
			foreach (object obj in views)
			{
				Autodesk.Revit.DB.View view = obj as Autodesk.Revit.DB.View;
				if ((int)view.ViewType == 6)
				{
					string mostNearPaperSize = this.getMostNearPaperSize(this.m_printMgr.PrinterName, view);
					if (!dictionary.ContainsKey(mostNearPaperSize) && !string.IsNullOrEmpty(mostNearPaperSize))
					{
						dictionary.Add(mostNearPaperSize, new List<Autodesk.Revit.DB.View>
						{
							view
						});
					}
					else
					{
						dictionary[mostNearPaperSize].Add(view);
					}
				}
				else if (!dictionary.ContainsKey(sCurSizeName) && !string.IsNullOrEmpty(sCurSizeName))
				{
					dictionary.Add(sCurSizeName, new List<Autodesk.Revit.DB.View>
					{
						view
					});
				}
				else
				{
					dictionary[sCurSizeName].Add(view);
				}
			}
			return dictionary;
		}

		public bool printViewWithSpecifySize(printType type)
		{
			try
			{
				if (type == printType.PT_OneView || type == printType.PT_ViewOneFile)
				{
					return this.SubmitPrint();
				}
				if (!this.addGBPaperSize(this.m_printMgr.PrinterName))
				{
					return false;
				}
				this.m_printMgr = this.m_commandData.Application.ActiveUIDocument.Document.PrintManager;
                Autodesk.Revit.DB.PaperSize paperSize = this.m_printMgr.PrintSetup.CurrentPrintSetting.PrintParameters.PaperSize;
				PageOrientationType pageOrientation = this.m_printMgr.PrintSetup.CurrentPrintSetting.PrintParameters.PageOrientation;
				ViewSet views = this.m_printMgr.ViewSheetSetting.CurrentViewSheetSet.Views;
				Dictionary<string, List<Autodesk.Revit.DB.View>> dictionary = this.createSizeGroup(views, this.m_commandData.Application.ActiveUIDocument.Document, paperSize.Name);
				if (dictionary.Count > 0)
				{
                    Autodesk.Revit.DB.PaperSize paperSize2 = paperSize;
					foreach (KeyValuePair<string, List<Autodesk.Revit.DB.View>> keyValuePair in dictionary)
					{
						bool flag = false;
						if (paperSize2.Name != keyValuePair.Key)
						{
                            Autodesk.Revit.DB.PaperSize paperSizeByName = this.getPaperSizeByName(keyValuePair.Key, this.m_printMgr.PaperSizes);
							if (paperSizeByName != null)
							{
								this.m_printMgr.PrintSetup.CurrentPrintSetting.PrintParameters.PaperSize = paperSizeByName;
								paperSize2 = paperSizeByName;
								this.m_printMgr.PrintSetup.Save();
							}
							else
							{
								YJKMessageBox.Show("paperSize is null");
								flag = true;
							}
						}
						if (!flag)
						{
							foreach (Autodesk.Revit.DB.View view in keyValuePair.Value)
							{
								if (view != null)
								{
									PageOrientationType pageOrientation2 = this.m_printMgr.PrintSetup.CurrentPrintSetting.PrintParameters.PageOrientation;
									PageOrientationType viewOrientationType = this.GetViewOrientationType(view);
									if (pageOrientation2 != viewOrientationType)
									{
										this.m_printMgr.PrintSetup.CurrentPrintSetting.PrintParameters.PageOrientation = viewOrientationType;
										this.m_printMgr.PrintSetup.Save();
									}
									this.m_printMgr.SubmitPrint(view);
								}
							}
						}
					}
					PrintSetting printSetting = this.m_printMgr.PrintSetup.CurrentPrintSetting as PrintSetting;
					if (printSetting != null && printSetting.Name.Equals("HYPrintSetting"))
					{
                        Autodesk.Revit.DB.PaperSize paperSize3 = this.m_printMgr.PrintSetup.CurrentPrintSetting.PrintParameters.PaperSize;
						PageOrientationType pageOrientation3 = this.m_printMgr.PrintSetup.CurrentPrintSetting.PrintParameters.PageOrientation;
						if (!paperSize3.Name.Equals(paperSize.Name) || pageOrientation3 != pageOrientation)
						{
							this.m_printMgr.PrintSetup.CurrentPrintSetting.PrintParameters.PaperSize = paperSize;
							this.m_printMgr.PrintSetup.CurrentPrintSetting.PrintParameters.PageOrientation = pageOrientation;
							this.m_printMgr.PrintSetup.Save();
						}
					}
				}
			}
			catch (Exception)
			{
				PrintMgr.MyMessageBox("打印失败，请更换虚拟打印机。");
			}
			return true;
		}

		private IList<Element> getDocAllTitleBlocks(Autodesk.Revit.DB.Document doc, ElementId viewId)
		{
			new List<Element>();
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc, viewId);
			filteredElementCollector.OfClass(typeof(FamilyInstance)).OfCategory(BuiltInCategory.OST_TitleBlocks);
			return filteredElementCollector.ToElements();
		}

		private Element getDefTitleBlock(Autodesk.Revit.DB.Document doc, ElementId viewId)
		{
			Element result = null;
			IList<Element> docAllTitleBlocks = this.getDocAllTitleBlocks(doc, viewId);
			if (docAllTitleBlocks.Count > 0)
			{
				result = docAllTitleBlocks[0];
			}
			return result;
		}

		private void getTitleBlockWidthHight(Element defEle, ref double dHight, ref double dWidth)
		{
			dHight = (dWidth = 0.0);
			if (defEle != null)
			{
				double dFeet = defEle.GetParameter("图纸高度").AsDouble();
				double dFeet2 = defEle.GetParameter("图纸宽度").AsDouble();
				dHight = UnitConversion.feetToMM(dFeet);
				dWidth = UnitConversion.feetToMM(dFeet2);
			}
		}

		private bool isExistPrintSet(string sNewName, ref Element ele)
		{
			bool result = false;
			foreach (ElementId elementId in this.m_commandData.Application.ActiveUIDocument.Document.GetPrintSettingIds())
			{
				Element element = this.m_commandData.Application.ActiveUIDocument.Document.GetElement(elementId);
				if (element.Name.Equals(sNewName))
				{
					result = true;
					ele = element;
					break;
				}
			}
			return result;
		}

		private Element savePrintSetting(string sNewName, PrintManager printMgr)
		{
			Element result = null;
			if (!this.isExistPrintSet(sNewName, ref result))
			{
				printMgr.PrintSetup.SaveAs(sNewName);
				this.isExistPrintSet(sNewName, ref result);
			}
			return result;
		}

		private double getOneViewPrintSize(Autodesk.Revit.DB.View view, ref double dH, ref double dW)
		{
			double result = 0.0;
			double num = 10.0;
			if (view != null)
			{
				double num2 = Math.Abs(view.Outline.Max.U - view.Outline.Min.U);
				double num3 = Math.Abs(view.Outline.Max.V - view.Outline.Min.V);
				num2 = UnitConversion.feetToMM(num2);
				num3 = UnitConversion.feetToMM(num3);
				result = num2 * num3;
				dH = num3 + num;
				dW = num2 + num;
			}
			return result;
		}

		private bool addGBPaperSize(string sPrinterName)
		{
			try
			{
				MyPaperSize myPaperSize = new MyPaperSize();
				foreach (KeyValuePair<string, pSize> keyValuePair in GBPaperSize.Instance().m_dicGBPSize)
				{
					myPaperSize.AddCustomPaperSize(sPrinterName, keyValuePair.Key, keyValuePair.Value.m_Width * 10f, keyValuePair.Value.m_Height * 10f);
				}
			}
			catch (Exception)
			{
				PrintMgr.MyMessageBox("打印失败，请更换虚拟打印机。");
				return false;
			}
			return true;
		}

		private PageOrientationType GetViewOrientationType(Autodesk.Revit.DB.View view)
		{
            PageOrientationType result = (PageOrientationType)1;
			double num = 0.0;
			double num2 = 0.0;
			this.getOneViewPrintSize(view, ref num, ref num2);
			if (num > num2)
			{
				result = 0;
			}
			return result;
		}

		private string getMostNearPaperSize(string sPrinterName, Autodesk.Revit.DB.View view)
		{
			double viewH = 0.0;
			double viewW = 0.0;
			this.getOneViewPrintSize(view, ref viewH, ref viewW);
			PageOrientationType viewOrientationType = this.GetViewOrientationType(view);
            return GBPaperSize.Instance().getSelfPaperSizeName(sPrinterName, viewH, viewW, (int)viewOrientationType == 1);
		}

		private ExternalCommandData m_commandData;

		private PrintManager m_printMgr;
	}
}
